#include "Codec.h"

#include "decoder/FFMpegAACDecoder.h"
#include "decoder/H264MediaCodecDecoder.h"
#include "decoder/X264Decoder.h"
#include "encoder/FdkAACEncoder.h"
#include "encoder/H264MediaCodecEncoder.h"
#include "encoder/X264Encoder.h"

IDecoder *
Codec_CreateDecoder(CodecType codecType, DecoderParam &param, IDecodeCallback *pDecoderCallback) {
  IDecoder *pDecoder = nullptr;
  switch (codecType) {
    case CodecType_AAC:
      pDecoder = new FFMpegAACDecoder(pDecoderCallback);
      break;
    case CodecType_H264MediaCodec:
      pDecoder = new H264MediaCodecDecoder(pDecoderCallback);
      break;
    case CodecType_X264:
      pDecoder = new X264Decoder(pDecoderCallback);
      break;
  }

  if (pDecoder && !pDecoder->initDecoder(param)) {
    Codec_DestroyDecoder(&pDecoder);
  }

  return pDecoder;
}

void Codec_DestroyDecoder(IDecoder **ppDecoder) {
  if (*ppDecoder) {
    (*ppDecoder)->releaseDecoder();
    DELETE_PTR(*ppDecoder)
  }
}

bool Codec_StartDecode(IDecoder *pDecoder, AVPacket *pPacket) {
  if (pDecoder) {
    return pDecoder->startDecode(pPacket);
  }

  return false;
}

IEncoder *
Codec_CreateEncoder(CodecType codecType, EncoderParam &param, IEncodeCallback *pEncoderCallback) {
  IEncoder *pEncoder = nullptr;
  switch (codecType) {
    case CodecType_AAC:
      pEncoder = new FdkAACEncoder(pEncoderCallback);
      break;
    case CodecType_H264MediaCodec:
      pEncoder = new H264MediaCodecEncoder(pEncoderCallback);
      break;
    case CodecType_X264:
      pEncoder = new X264Encoder(pEncoderCallback);
      break;
  }

  if (pEncoder && !pEncoder->initEncoder(param)) {
    Codec_DestroyEncoder(&pEncoder);
  }

  return pEncoder;
}

void Codec_DestroyEncoder(IEncoder **ppEncoder) {
  if (*ppEncoder) {
    (*ppEncoder)->releaseEncoder();
    DELETE_PTR(*ppEncoder)
  }
}

bool Codec_StartEncode(IEncoder *pEncoder, AVFrame *pFrame) {
  if (pEncoder) {
    return pEncoder->startEncode(pFrame);
  }
  return false;
}